using Single.Core.Service;
using Single.Sugar.Service;
using Single.Sys.Entity;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using Single.Cache;

namespace Single.Sys.Service
{
    public class SysRoleMenuFunctionService : BaseService<SysRoleMenuFunction>
    {
        public List<SysRoleMenuFunction> GetByRoleId(long id)
        {
            return rep.GetList(m => m.RoleId.Equals(id)).ToList();
        }

        public virtual ServiceResult SetMenuFunction(long roleId, long[] mfIds)
        {
            var olds = rep.AsQueryable().Where(m => m.RoleId.Equals(roleId)).ToList();

            var iList = new List<SysRoleMenuFunction>();

            foreach (var mfid in mfIds)
            {
                if (!olds.Any(m => m.MenuFunctionId.Equals(mfid)))
                {
                    iList.Add(new SysRoleMenuFunction { RoleId = roleId, MenuFunctionId = mfid });
                }
            }

            var dList = new List<SysRoleMenuFunction>();

            olds.ForEach(m =>
            {
                if (!mfIds.Any(n => n.Equals(m.MenuFunctionId))) { dList.Add(m); }
            });

            var result = tenant.UseTran(() =>
            {
                rep.InsertRange(iList); rep.Delete(dList);
            });

            return UnknownResult(result.IsSuccess);
        }

        public bool VerifyPower(long userId, string path, bool isSuper)
        {
            if (!isSuper)
            {
                var mfRep = MoreRep<SysMenuFunction>();

                var paths = CacheHelper.GetOrCreate("sys_power_paths", 20, () =>
                {
                    return mfRep.AsQueryable().Where(m => !string.IsNullOrEmpty(m.Path)).Select(m => m.Path).ToList();
                });

                if (paths.Contains(path))
                {
                    var userPaths = CacheHelper.GetOrCreate($"sys_power_user_paths:{userId}", 20, () =>
                    {
                        return mfRep.AsQueryable().Where(m => !string.IsNullOrEmpty(m.Path))
                            .InnerJoin<SysRoleMenuFunction>((mf, rmf) => mf.Id == rmf.MenuFunctionId)
                            .InnerJoin<SysUserRole>((mf, rmf, ur) => rmf.RoleId == ur.RoleId)
                            .InnerJoin<SysRole>((mf, rmf, ur, r) => ur.RoleId == r.Id)
                            .Where((mf, rmf, ur, r) => ur.UserId == userId && r.Status.Equals("ok"))
                            .Select((mf, rmf, ur, r) => mf.Path).ToList();
                    });

                    return userPaths.Contains(path);
                }
            }

            return true;
        }
    }
}